package pl.pasu.ocrtc;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import android.content.Context;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.AssetManager;
import android.graphics.Bitmap;

import com.googlecode.tesseract.android.TessBaseAPI;

public class OcrReader {

    public enum Language {
        EN {

            @Override
            public String toString() {
                return "eng";
            }
        },
        PL {

            @Override
            public String toString() {
                return "pol";
            }
        }
    }
    private static final String TAG = "OcrReader";
    private Language mLanguage;
    private Context mContext;
    private static final String ENG_DATA_FILENAME = "eng.traineddata";
    private static final String PL_DATA_FILENAME = "pol.traineddata";
    private static final String TEST_IMG_FILENAME = "test2.png";

    public OcrReader(Context context, Language language) {
        mContext = context;
        mLanguage = language;
    }

    public void readImageText(final OcrDoneCallback callback, final Bitmap bmp) {
        new Thread(new Runnable() {

            @Override
            public void run() {
                Logger.i(TAG, "readImageText >> run");
                String path = getAppDataDir();
                TessBaseAPI baseApi = new TessBaseAPI();
                baseApi.setVariable(TessBaseAPI.VAR_CHAR_NUMERIC, "1");
                baseApi.setVariable(TessBaseAPI.VAR_CHAR_WHITELIST, "0123456789:");
                baseApi.setVariable(TessBaseAPI.VAR_CHAR_BLACKLIST, "abcdefghijklmnopqrstuwvxyABCDEFGHIJKLMNOPQRSTUWVXY#%()[]{}|\\/?<>");
                baseApi.setPageSegMode(TessBaseAPI.PSM_SINGLE_WORD);
                baseApi.init(path + "/", mLanguage.toString());
                baseApi.setImage(bmp);
                baseApi.setVariable(TessBaseAPI.VAR_CHAR_NUMERIC, "1");
                baseApi.setVariable(TessBaseAPI.VAR_CHAR_WHITELIST, "0123456789:");
                baseApi
                        .setVariable(TessBaseAPI.VAR_CHAR_BLACKLIST, "abcdefghijklmnopqrstuwvxyABCDEFGHIJKLMNOPQRSTUWVXY#%()[]{}|\\/?<>");
                baseApi.setPageSegMode(TessBaseAPI.PSM_SINGLE_WORD);
                String recognizedText = baseApi.getUTF8Text();
                baseApi.end();
                // Logger.i(TAG, "recognizedText=" + recognizedText);
                callback.onOcrDone(recognizedText);
            }
        }).start();
    }

    public void copyFilesToSd() {
        if (!checkExists()) {
            copyAssets();
        } else {
            Logger.i(TAG, "NO need to copyFilesToSd - already exists");
        }
    }

    private boolean checkExists() {
        String pathTess = getTessDataDir();
        String path = getAppDataDir();
        String[] files = {ENG_DATA_FILENAME, PL_DATA_FILENAME};
        for (String filename : files) {
            File f = new File(pathTess, filename);
            if (f == null || !f.exists()) {
                return false;
            }
        }
        File f = new File(path, TEST_IMG_FILENAME);
        if (f == null || !f.exists()) {
            return false;
        }
        return true;
    }

    private void copyAssets() {
        String pathTess = getTessDataDir();
        String path = getAppDataDir();
        AssetManager assetManager = mContext.getAssets();
        String[] files = {ENG_DATA_FILENAME, PL_DATA_FILENAME, TEST_IMG_FILENAME};
        // try {
        // files = assetManager.list("");
        // } catch (IOException e) {
        // Logger.e(TAG, e.getMessage());
        // }
        for (String filename : files) {
            InputStream in = null;
            OutputStream out = null;
            try {
                in = assetManager.open(filename);
                String finalPath = pathTess + "/" + filename;
                if (filename.equalsIgnoreCase(TEST_IMG_FILENAME)) {
                    finalPath = path + "/" + filename;
                }
                Logger.i(TAG, "copying to: " + finalPath);
                out = new FileOutputStream(finalPath);
                copyFile(in, out);
                in.close();
                in = null;
                out.flush();
                out.close();
                out = null;
            } catch (IOException e) {
                Logger.e(TAG, e.getMessage());
            }
        }
    }

    private void copyFile(InputStream in, OutputStream out) throws IOException {
        byte[] buffer = new byte[1024];
        int read;
        while ((read = in.read(buffer)) != -1) {
            out.write(buffer, 0, read);
        }
    }

    private String getAppDataDir() {
        try {
            String path = mContext.getPackageManager().getPackageInfo(mContext.getPackageName(), 0).applicationInfo.dataDir
                    + "/ocr";
            File f = new File(path);
            if (!f.exists()) {
                f.mkdirs();
            }
            return path;
        } catch (NameNotFoundException e) {
            e.printStackTrace();
        }
        return null;
    }

    private String getTessDataDir() {
        try {
            String path = mContext.getPackageManager().getPackageInfo(mContext.getPackageName(), 0).applicationInfo.dataDir
                    + "/ocr/tessdata";
            File f = new File(path);
            if (!f.exists()) {
                f.mkdirs();
            }
            return path;
        } catch (NameNotFoundException e) {
            e.printStackTrace();
        }
        return null;
    }
}
